#include <iostream>
#include <memory>

using namespace std;

/**
 * Before the C++98 Standard added the keyword typename to the language, C++ used the keyword class in
 * this particular context. That is, you can write the template definition this way:
 * template <class AnyType>
 * The C++ Standard treats the two keywords identically when they are used in this context.
 */
template <typename AnyType>
void Swap(AnyType &a, AnyType &b){
    AnyType temp;
    temp = a;
    a = b;
    b = temp;
}

template <class T>
void sub(T &a, T &b){
    a = a - b;
}

template <class T1, class T2>
void f(T1 a, T2 b){
    return a + b;
}

struct job{
    char name[40];
    double salary;
    int floor;
};

/*non template function. The compiler will select this function at first.*/
void job_p(job &a, job &b){
    using namespace std;
    cout<<""<<endl;
}

template <typename T>
void job_p(T &a){

}
/*explicit specialization for the job type*/
template <>
void job_p<job>(job &a){

}

template void job_p<job>(job &a);

/**instantiations and specializations
 * instantiation: the compiler uses the template to generate a function definition for a particular type,
 * the result is termed an instantiation of the template.
*/

template<class T1, class T2>
auto gt(T1 x, T2 y) -> decltype(x+y){
    return x +y;
}

int main(){
    
    int a = 2;
    int b = 3;
    cout<<"int type before swap a:"<<a<<"\tb:"<<b<<endl;
    Swap<int>(a,b);
    cout<<"int type after  swap a:"<<a<<"\tb:"<<b<<endl;
    double ad = 4.0;
    double bd = 5.0;
    cout<<"double type before swap ad:"<<ad<<"\tbd:"<<bd<<endl;
    Swap<double>(ad, bd);
    cout<<"double type after  swap ad:"<<ad<<"\tbd:"<<bd<<endl;

    cout<<"let swap two struct job vars"<<endl;

}